var fs = require('fs');

var rooms = [];
var playerList = [];
var playerNameList = [];

/**
* 响应登录页面
* @request 无参数
* @reponse 静态网页/web/index.html
*/
function home(request,response){
  response.writeHead(200,{'Content-Type':'text/html'});
  fs.createReadStream(__dirname+"/web/index.html").pipe(response);
}

/*
* 处理匹配大厅静态路由
* @request object 包含1个请求参数
* @request param playerName 发起请求的用户名
*/
function hall(request,response){
  response.writeHead(200,{'Content-Type':'text/html'});
  let player = getPlayerByPlayerName(request.playerName);
  if(player && !player.roomId){ //玩家已合法登录过，且未加入房间
    fs.createReadStream(__dirname+"/web/rooms.html").pipe(response);
  }else if(!player){ //没有登录过，重定向到登录页面
    response.writeHead(302,{'Location':'/'});
    response.end();
  }else if(player.roomId){ //玩家已登录过且已加入房间
    response.end("You have already join a room!");
  }else{
    response.end("Unknown Error");
  }
}

/**
* @request object 包含2个请求参数 
* @request_param playerName string 玩家名称
* @request_param isPreemptive boolean 是否抢先手
* @response 静态网页/web/rooms.html
*/
function login(request,response){
    response.writeHead(200,{'Content-Type':'text/html'});
    //合法用户名校验
    if(request.playerName && request.playerName != ''){  
      if(playerNameList.indexOf(request.playerName) == -1){ //新用户登录
        //解析创建玩家
        if(playerList.push(request)){
          console.log(request.playerName+"成功登录");
          playerNameList.push(request.playerName);
          console.log("当前共有%s名玩家在线",playerList.length);
        }
        //登录成功，响应大厅网址
        response.end("/hall?playerName="+request.playerName);
      }else{ //已经登录过了，直接响应为当前房间
        response.end("/game?playerName="+request.playerName);
      }
    }else{
      fs.createReadStream(__dirname+"/web/index.html").pipe(response);
    }
}

/**
* 当前空房间列表
* @request 包含1个请求参数
* @request_param playerName 发起请求的玩家名称
* @response 空房间
*/
function showRooms(request,response){
  response.writeHead(200,{'Content-Type':'text/json'});
  //进行登录鉴权
  if(request.playerName != '' && playerNameList.indexOf(request.playerName) != -1){
    availableRooms = [];
    for(var i in rooms){
      if(rooms[i].players.length == 1){
        availableRooms.push(rooms[i]);
      }
    }
    response.end(JSON.stringify(availableRooms));
  }else{ //未登录，不允许访问
    response.end("It seems that you have not login");
  }
}

/*
* 创建房间
* @request 包含1个请求参数
* @request_param playerName 发起请求的玩家名称
* @response 创建的房间号
*/
function createRoom(request,response){
  response.writeHead(200,{'Content-Type':'text/json'});
  //进行登录鉴权
  let player = getPlayerByPlayerName(request.playerName);
  if(player && !player.roomId){
    let players = [];
    let roomId = Math.round(Math.random()*10000000000);
    let board = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
    let room = {'roomId':roomId,'board':board,'players':players,former:''};
    player.roomId = roomId;
    room.players.push(player);
    rooms.push(room);
    //将roomId响应给client
    response.end(JSON.stringify({'roomId':roomId}));
  }else if(!player){
    response.end("It seems that you have not login");
  }else if(player && player.roomId){
    response.end("You have already join room:"+player.roomId);
  }else{
    reponse.end("Unknown Error");
  }
}

/*
* 加入房间
* @request 包含2个请求参数
* @request_param playerName 发起请求的玩家名称
* @request_param roomId 要加入的房间id
* @response 响应先手
*/
function joinRoom(request,response){
  response.writeHead(200,{'Content-Type':'text/json'});
  var player = getPlayerByPlayerName(request.playerName);

  let room = null;
  //进行登录鉴权
  if(player && !player.roomId){
    //该房间存在且有空位，且当前用户未在此房间
    room = getRoomById(request.roomId);
    player.roomId = request.roomId;
    if(room && room.players.length == 1 && room.players[0]!= player){ 
      room.players.push(player);
      
      room.players[0].playerValue = -1;
      room.players[1].playerValue = -1;
      //初始化先后手
      if(room.players[0].isPreemptive != room.players[1].isPreemptive){
        if(room.players[0].isPreemptive){
          room.former = room.players[0].playerName;
          room.later = room.players[1].playerName;
          room.players[0].playerValue=1;
        }else{
          room.former = room.players[1].playerName;
          room.later = room.players[0].playerName;
          room.players[1].playerValue=1;
        }
      }else{
        //随机分配先后手
        let rad = Math.round(Math.random()*100)%2;
        let formerPlayer = room.players[rad];
        let laterPlayer = room.players[Math.abs(1-rad)];

        room.former = formerPlayer.playerName;
        room.later = laterPlayer.playerName;

        formerPlayer.playerValue = 1;
      }
      response.end(JSON.stringify({'former':room.former}));
    }else{
      response.end("Sorry, you can not join this room");
    }
  }else if(player == null){
    response.end("It seems that you have not login");
  }else if(player.roomId != null){
    response.end("You have already join room:"+player.roomId);
  }else{
    response.end("Unknown Error");
  }
  //console.log(JSON.stringify(room.players));
}

/*
* 房主检查自己的房间是否有对手加入，建议轮询
* @request 包含2个请求参数
* @request_param playerName 发起请求的玩家名
* @request_param roomId 要检查的房间id
* @response 响应当前房间的先手
*/
function checkRoom(request,response){
  response.writeHead(200,{'Content-Type':'text/json'});
  let room = getRoomById(request.roomId);
  let timer = setInterval(()=>{
    if(room && room.former){
      response.end(JSON.stringify({'former':room.former}));
      clearInterval(timer);
    }
  },1000);
}

/*
* 响应游戏页面
* @request 包含1个请求参数
* @request_param playerName 发起请求的玩家名
* @response html
*/
function game(request,response){
	//用户鉴权
	let player = getPlayerByPlayerName(request.playerName);
	if(player){//用户已登录
		response.writeHeader(200,{'Content-Type':'text/html'});
		fs.createReadStream(__dirname+"/web/grid.html").pipe(response);
	}else{
		response.writeHeader(404,{'Content-Type':'text/html'});
		response.end('Please login !');
	}
}


/*
* 执行落子方法
* @request 包含2个请求参数
* @request_param playerName 发起请求的玩家名称
* @request_param locate     玩家落子位置，例如r1c1
* @response 响应消子的位置数组，例如['r1c1','r1c3']
*/
function drop(request,response){
  let player = getPlayerByPlayerName(request.playerName);
  if(player && player.roomId){
    let room = getRoomById(player.roomId);
    let locate = request.locate;
    let i = locate[1];
    let j = locate[3];

    //console.log(`playerValue:${player.playerValue}`);
    //console.log(JSON.stringify(player));

    room.board[i][j] = player.playerValue;

    let remove = getRemoveList(room,i,j,player.playerValue);
    
    let waitPlayer = request.playerName==room.players[0].playerName?room.players[1]:room.players[0];
    //填充回合内容
    room.combat = {
      removeList:remove,//消子的id矩阵
      accept : waitPlayer.playerName, // 等候落子的玩家
      dropLocation:locate //落子的位置
    }
    
    //console.log(JSON.stringify(room.combat));
    //响应要被消子的id数组
    response.end(JSON.stringify(room.combat.removeList));
  }else{
    response.end("你尚未登录或未加入房间");
  }
}

/*
* 查询消子数组，用于查询对手方是否已落子产生消子
* request 包含1个请求参数
* request_param roomId 要查询的房间id
* response 响应对手落子位置、消子位置数组
*/
function checkDrop(request,response){
  let interval = setInterval(()=>{
    let room = getRoomById(request.roomId);
    if(room && room.combat){
      clearInterval(interval);
      response.end(JSON.stringify(room.combat));
    }
    room.combat = null;
  },1000);
}

/*
* 检查是否已出现赢家
*/
function checkWin(request,response){
  let winner = null;
  let room = getRoomById(request.roomId);
  let formerWinVector = [1,1,1,1];
  let laterWinVector = [-1,-1,-1,-1];

  //检查行上是否已出现赢家
  for(let i = 0;i<room.board.length;i++){
    if(room.board[i].toString() == formerWinVector.toString()){
      winner = room.former;
      break;
    }else if(room.board[i].toString() == laterWinVector.toString()){
      //let index = room.player.indexOf(getPlayerByPlayerName(room.former));
      winner = room.later;
      break;
    }
  }
  
  if(!winner){ //行上没有出现赢家，再检查列上
    for(let j = 0;j<room.board.length;j++){
      if(getColumn(room.board,j).toString() == formerWinVector.toString()){
        winner = room.former;
        break;
      }else if(getColumn(room.board,j).toString() == laterWinVector.toString()){
        winner = room.later;
        break;
      }
    }
  }

  room.winner = winner;
  if(winner)
    console.log(`winner:${winner}`);

  response.end(JSON.stringify({'winner':room.winner}));
}

/*
* 根据对应的roomId查询room对象
* @param id 要查询的roomId
* @return 返回命中的room，如无则null
*/
function getRoomById(id){
  for(var i in rooms){
    if(rooms[i].roomId=id)
      return rooms[i];
  }
  return null;
}

/*
* 根据playerName找到对应的player对象
* @param playerName 要查询的playerName
* @return 返回命中的player，如无则null
*/
function getPlayerByPlayerName(playerName){
  for(var i in playerList){
    if(playerList[i].playerName==playerName){
      return playerList[i];
    }
  }
  return null;
}

/*
* 获取消子数组
* 
*/
function getRemoveList(room,i,j,playerValue){
  let removeList = [];
  //获取原始数组
  let originBoard = JSON.parse(JSON.stringify(room.board));
  //更新room数组
  let updateRow = calculateVector(getRow(room.board,i),playerValue);
  let updateColumn = calculateVector(getColumn(room.board,j),playerValue);

  room.board = setRow(room.board,updateRow,i);
  room.board = setColumn(room.board,updateColumn,j);

  removeList = compare(originBoard,room.board);

  return removeList;
}

/*
* 实现行内消子
*/
function calculateVector(vector,playerValue){
  //获取有效棋子个数
  let chessNumber = getValidLength(vector);
  //获取执手方棋子个数
  let playerChessNumber = getPlayerChessNumber(vector,playerValue);
  console.log(`chessNumber:${chessNumber} playerChessNumber:${playerChessNumber}`);
  if(chessNumber == 3 && vector.indexOf(0)%3 == 0){
    if(playerChessNumber == 1 ){ //一撑乎
      if((vector.indexOf(0)-vector.indexOf(playerValue))%2==0){
        vector = removeOtherChess(vector,playerValue);
      }
    }else if(playerChessNumber == 2){ //二顶一、一夹沟
      vector = removeOtherChess(vector,playerValue);
    }
  }else if(chessNumber == 4){
    if(playerChessNumber ==2){
      if(vector.toString() != [1,-1,1,-1].toString() 
        && vector.toString() != [-1,1,-1,1].toString()){
        vector = removeOtherChess(vector,playerValue);
      }
    }else if(playerChessNumber == 1){
      if(vector[0] == playerValue || vector[3]==playerValue){
        vector = removeOtherChess(vector,playerValue);
      }
    }
  }
  return vector;


}

//获取向量中有效棋子个数
function getValidLength(vector){
  let i = 0;
  for(var index = 0 ; index < vector.length; index++){
    if(vector[index]!=0)
      i++;
  }
  return i;
}

//获取向量中执手子个数
function getPlayerChessNumber(vector,playerValue){
  let number = 0;
  for(i in vector){
    if(vector[i]==playerValue)
      number++;
  }
  return number;
}

//移除其它类型棋子
function removeOtherChess(vector,keepValue){
  for(i in vector){
    if(vector[i]!=keepValue)
      vector[i] = 0;
  }
  return vector;
}

//获取行向量
function getRow(board,i){
  return board[i];
}

//设置行向量
function setRow(board,vector,i){
  board[i] = vector;
  return board;
}

//获取列向量
function getColumn(board,j){
  let column = [];
  for(row in board){
    column.push(board[row][j]);
  }
  return column;
}

//设置列向量
function setColumn(board,vector,j){
  for(let index = 0 ;index<board.length;index++){
    board[index][j]=vector[index];
  }
  return board;
}

//比较前后2个数组变化
function compare(originBoard,updateBoard){
  let changeList = [];
  for(var i = 0 ; i < originBoard.length;i++){
    for(var j = 0 ; j < originBoard[i].length;j++){
      if(originBoard[i][j] != updateBoard[i][j] && updateBoard[i][j]==0){
        changeList.push(`r${i}c${j}`);
      }
    }
  }
  return changeList;
}

//填充rooms
function setRooms(rs){
  rooms = rs;
}


module.exports = {
    home : home,
    hall : hall,
    game : game,
    drop : drop,
    login : login,
    checkWin,checkWin,
    joinRoom : joinRoom,
    showRooms : showRooms,
    checkRoom : checkRoom,
    checkDrop : checkDrop,
    createRoom : createRoom,
    /*非响应*/
    setRooms:setRooms,
    getRoomById:getRoomById,
    calculateVector:calculateVector,
    getRemoveList:getRemoveList,
    removeOtherChess:removeOtherChess
}

/*
* room:
*   roomId  int     10位的整数,标识此房间唯一的id
*   players array   长度为2的数组，包含2个玩家所有信息
*   former  string  先手玩家的playerName
*   later   string  后手玩家的playerName
*   winner  string  赢家的playerName
*   board   [][]    当前的棋盘数组
*   removeList  []  消子数组
*/

/*
* player
*   roomId        int       玩家所在的房间id
*   playerName    string    玩家的用户名
*   isPreemptive  boolean   是否抢先手
*   isFormer      boolean   是否为先手
*   playerValue   int       玩家值
*/
